package dataHandlers.objectData;


import java.util.LinkedList;
import java.util.concurrent.ConcurrentHashMap;


import clientData.ForumData;
import clientData.ForumDataInt;
import clientData.MemberData;
import clientData.MemberDataInt;
import clientData.PostData;
import clientData.PostDataInt;
import clientData.TopicData;
import clientData.TopicDataInt;
import dataHandlers.DataControlerInt;
import domainModel.Forum;
import domainModel.ForumInt;
import domainModel.Member;
import domainModel.MemberInt;
import domainModel.Post;
import domainModel.PostInt;
import domainModel.Topic;
import domainModel.TopicInt;
import exception.ForumNotFoundException;
import exception.PostNotExistException;
import exception.TopicNotFoundException;

public class ObjectDataController implements DataControlerInt {

	private static DataControlerInt singletonObject;
	
	private ConcurrentHashMap<Integer, ForumInt> forums;
	private ConcurrentHashMap<String,MemberInt> members;
	
	
	private ObjectDataController(){
		this.forums = new ConcurrentHashMap<Integer, ForumInt>();
		this.members = new ConcurrentHashMap<String, MemberInt>();
	}
	
	public static DataControlerInt getDataControler(){
		if (singletonObject == null) {
			singletonObject = new ObjectDataController();
		}
		return singletonObject;
	}
	
	
	@Override
	public int addForum(String userName, String forumName) {
		ForumInt newForum = new Forum(forumName, this.members.get(userName));
		this.forums.put(newForum.getId(), newForum);
		return newForum.getId();
	}

	@Override
	public void addFriend(String userName, String friendUserName) {
		MemberInt user = this.members.get(userName);
		MemberInt friend = this.members.get(friendUserName);
		user.addFriend(friend);
	}

	@Override
	public void addMember(String userName, int id, String email,
			String firstName, String lastName) {
		MemberInt newMember = new Member(id,userName, email, firstName, lastName);
		this.members.put(newMember.getUserName(), newMember);
	}

	@Override
	public int addPost(String userName, int forumId, int topicId, String title, String content) throws ForumNotFoundException, TopicNotFoundException {
		
		ForumInt forum = this.forums.get(forumId);
		if(forum == null)
				throw new ForumNotFoundException();
		
		TopicInt topic = forum.getTopics().get(topicId);
		if(topic == null)
				throw new TopicNotFoundException();
		
		
			MemberInt creator = this.members.get(userName);
			PostInt newPost = new Post(creator, title, content);
			topic.addPost(newPost);
		
		
		
	//	this.forums.get(forumId).getTopics().get(topicId).addPost(newPost);
		
		return newPost.getId();
	}

	@Override
	public int addTopic(String userName, int forumId, String title) throws ForumNotFoundException {
		
		ForumInt forum = this.forums.get(forumId);
		if(forum == null)
				throw new ForumNotFoundException();
		
		
			MemberInt creator = this.members.get(userName);
			TopicInt newTopic = new Topic(title,creator);
			forum.addTopic(newTopic);
	
		
		return newTopic.getId();
		//this.forums.get(forumId).addTopic(newTopic);
	}

	@Override
	public void editPost(int postId,int forumId,int topicId, String newContent, String newTitle) throws ForumNotFoundException, TopicNotFoundException {
		ForumInt forum = this.forums.get(forumId);
		if(forum == null)
				throw new ForumNotFoundException();
		TopicInt topic = forum.getTopics().get(topicId);
		if(topic == null)
				throw new TopicNotFoundException();
		
		
		PostInt postClone = topic.getPosts().get(postId).clone();
		postClone.editPost(newContent, newTitle);
		topic.addPost(postClone);
		
		
		
		//this.forums.get(forumId).getTopics().get(topicId).getPosts().get(postId).editPost(newContent, newTitle);
	}

	@Override
	public LinkedList<ForumDataInt> getForums() {
		LinkedList<ForumDataInt> forums = new LinkedList<ForumDataInt>();
		
			
			for(ForumInt forum : this.forums.values())
			{
				MemberInt mem = forum.getCreator();
				MemberDataInt mdata = new MemberData(mem.getId(),mem.getUserName(),mem.getEmail(),mem.getFirstName(),mem.getLastName());
				ForumDataInt fdata = new ForumData(forum.getId(),forum.getName(),mdata);
				forums.add(fdata);
			}
		
	
		return forums;
	}

	@Override
	public LinkedList<MemberDataInt> getFriends(String userName) {
		LinkedList<MemberInt> members = this.members.get(userName).getFriends();
		LinkedList<MemberDataInt> ans = new LinkedList<MemberDataInt>();
		for (MemberInt mem : members){
			MemberDataInt md = new MemberData(mem.getId(),mem.getUserName(),mem.getEmail(),mem.getFirstName(),mem.getLastName());
			ans.add(md);
		}
		return ans;
	}

/*	@Override
	public LinkedList<MemberInt> getMembers() {
		return null;
	}
*/
	
	@Override
	public LinkedList<MemberDataInt> getMembersByPrefix(String userNamePrefix) {
		LinkedList<MemberDataInt> ans = new LinkedList<MemberDataInt>();
		for (MemberInt mem : this.members.values()){
			if (mem.getUserName().startsWith(userNamePrefix)){
				MemberDataInt tmpMember = new MemberData(mem.getId(),mem.getUserName(),mem.getEmail(),mem.getFirstName(),mem.getLastName());
				ans.add(tmpMember);
			}
		}
		return ans;
	}

	@Override
	public LinkedList<PostDataInt> getPosts(int forumId, int topicId) throws ForumNotFoundException, TopicNotFoundException {
		
		
		ForumInt forum = this.forums.get(forumId);
		if(forum == null)
				throw new ForumNotFoundException();
		TopicInt topic = forum.getTopics().get(topicId);
		if(topic == null)
				throw new TopicNotFoundException();
		
		
		LinkedList<PostDataInt> dataPosts = null;
		
		
			ConcurrentHashMap<Integer,PostInt> posts = topic.getPosts();
			dataPosts = new LinkedList<PostDataInt>();
			for (PostInt post : posts.values()){
				MemberInt creator = post.getCreator();
				MemberDataInt md = new MemberData(creator.getId(),creator.getUserName(), creator.getEmail(), creator.getFirstName(), creator.getLastName());
				PostDataInt dp = new PostData(post.getId(),post.getTitle(), post.getContent(), post.getCreationTime(), post.getEditingTime(),md );
				dataPosts.add(dp);
			
		}
		
		
		return dataPosts;
	}

	@Override
	public LinkedList<TopicDataInt> getTopics(int forumId) throws ForumNotFoundException {
		
		ForumInt forum = this.forums.get(forumId);
		if(forum == null)
				throw new ForumNotFoundException();
		
		LinkedList<TopicDataInt> dataTopics = null;
		
	
			ConcurrentHashMap<Integer, TopicInt> topics = forum.getTopics();
			dataTopics = new LinkedList<TopicDataInt>();
			for (TopicInt topic : topics.values()){
				MemberInt creator = topic.getCreator();
				MemberDataInt md = new MemberData(creator.getId(),creator.getUserName(), creator.getEmail(), creator.getFirstName(), creator.getLastName());
				TopicDataInt dt = new TopicData(topic.getId(),topic.getCreationTime(),topic.getTitle(),md);
				dataTopics.add(dt);
	
		}
		
		return dataTopics;
	}




	
	public void removeForum(int forumId) throws ForumNotFoundException {
		ForumInt forum = this.forums.get(forumId);
		if(forum == null)
				throw new ForumNotFoundException();
		
			this.forums.remove(forumId);
		
			
		
		

	}

	@Override
	public void removeFriend(String userName, String friendUserName) {
		MemberInt friend = this.members.get(friendUserName);
		this.members.get(userName).getFriends().remove(friend);


	}

	
	public void removeMember(String userName) {
		this.members.remove(userName);

	}

	
	public void removePost(int forumId, int topicId, int postId) throws TopicNotFoundException, ForumNotFoundException {
		
		ForumInt forum = this.forums.get(forumId);
		if(forum == null)
				throw new ForumNotFoundException();
		TopicInt topic = forum.getTopics().get(topicId);
		if(topic == null)
				throw new TopicNotFoundException();
		
		
			topic.removePost(postId);
		
		//ForumInt forum = this.forums.get(forumId);
		//TopicInt topic = forum.getTopics().get(topicId);
		

	}


	public void removeTopic(int forumId, int topicId) throws ForumNotFoundException {
		ForumInt forum = this.forums.get(forumId);
		if(forum == null)
				throw new ForumNotFoundException();
		
			forum.removeTopic(topicId);
		
		

	}

	@Override
	public boolean forumExist(int forumId) {
		return this.forums.containsKey(forumId);
		
	}

	@Override
	public boolean postExist(int forumId, int topicId, int postId) {
		ForumInt forum = this.forums.get(forumId);
		TopicInt topic = forum.getTopics().get(topicId);
		return topic.getPosts().containsKey(postId);
	}

	@Override
	public boolean topicExist(int forumId, int topicId) {
		ForumInt forum = this.forums.get(forumId);
		
		return forum.getTopics().containsKey(topicId);
	}

	@Override
	public boolean userExist(String userName) {
		return this.members.containsKey(userName);
	}

	@Override
	public boolean isCreatorOfPost(int forumId, int topicId, int PostId,
			String userName) throws ForumNotFoundException, TopicNotFoundException, PostNotExistException {
		
		ForumInt forum = this.forums.get(forumId);
		if(forum == null)
				throw new ForumNotFoundException();
		
		TopicInt topic = forum.getTopics().get(topicId);
		
		if(topic == null)
				throw new TopicNotFoundException();
		
		PostInt post = topic.getPosts().get(PostId);
		
		if(post == null)
			throw new PostNotExistException();
		
		
		return post.getCreator().getUserName().equals(userName);
		
		
	}
	
	public String getTopicCreator(int forumId,int topicId)
	{
		ForumInt forum = this.forums.get(forumId);
		TopicInt topic = forum.getTopics().get(topicId);
		return topic.getCreator().getUserName();
	}
	

	public ForumDataInt getForumData(int forumId)
	{
		ForumInt forum = this.forums.get(forumId);
		MemberInt mem = forum.getCreator();
		MemberDataInt mdata = new MemberData(mem.getId(),mem.getUserName(),mem.getEmail(),mem.getFirstName(),mem.getLastName());
		ForumDataInt fdata = new ForumData(forum.getId(),forum.getName(),mdata);
	
		return fdata;
	}
	public TopicDataInt getTopicData(int forumId, int topicId)
	{
		ForumInt forum = this.forums.get(forumId);
		TopicInt topic = forum.getTopics().get(topicId);
		
		MemberInt creator = topic.getCreator();
		MemberDataInt md = new MemberData(creator.getId(),creator.getUserName(), creator.getEmail(), creator.getFirstName(), creator.getLastName());
		TopicDataInt dt = new TopicData(topic.getId(),topic.getCreationTime(),topic.getTitle(),md);
		return dt;
	}
	
	public PostDataInt getPostData(int forumId,int topicId, int postId)
	{
		
		ForumInt forum = this.forums.get(forumId);
		TopicInt topic = forum.getTopics().get(topicId);
		PostInt post = topic.getPosts().get(postId);
		
		
		MemberInt creator = post.getCreator();
		MemberDataInt md = new MemberData(creator.getId(),creator.getUserName(), creator.getEmail(), creator.getFirstName(), creator.getLastName());
		PostDataInt dp = new PostData(post.getId(),post.getTitle(), post.getContent(), post.getCreationTime(), post.getEditingTime(),md );
	
		return dp;
	}
}
